package module

import (
	"fmt"
	"github.com/gin-gonic/gin"
)

type (
	HandlerFunc func(ctx *gin.Context)
	Group       string
	Path        string
	Method      string
	PathValue   int
)

const (
	POST    = Method("POST")
	GET     = Method("GET")
	PUT     = Method("PUT")
	DELETE  = Method("DELETE")
	PATCH   = Method("PATCH")
	HEAD    = Method("HEAD")
	OPTIONS = Method("OPTIONS")
)

var (
	m         *module
	a         *api
	moduleMap = make(map[string]*module, 0)
	controllerMap = make(map[string]Base, 0)
)

func LoadController(base Base,key string)  {
	if _, ok := controllerMap[key]; !ok {
		controllerMap[key] = base
	}
}

func Register(base Base, key string) *Group {
	m = newModule(base, key)
	if _, ok := moduleMap[key]; !ok {
		moduleMap[key] = m
	}
	fmt.Println("moduleMap:",moduleMap)
	return &m.group
}

func AddApi(key string) *Group {
	mm, ok := moduleMap[key]
	m = mm
	if !ok {
		return nil
	}
	return &mm.group
}


func RegisterRoute(router *gin.Engine) *gin.Engine {
	for _, v := range moduleMap {
		for _, ap := range v.apis {
			switch ap.method {
			case POST:
				router.Group(string(v.group)).GET(string(ap.path), getGinHandlerFunc(ap))
			case GET:
				router.Group(string(v.group)).GET(string(ap.path), getGinHandlerFunc(ap))
			case PUT:
				router.Group(string(v.group)).PUT(string(ap.path), getGinHandlerFunc(ap))
			case DELETE:
				router.Group(string(v.group)).DELETE(string(ap.path), getGinHandlerFunc(ap))
			}
		}
	}
	return router
}

func getGinHandlerFunc(ap *api) gin.HandlerFunc {
	return func(c *gin.Context) {
		ap.handler(c)
	}
}

func (t Group) WithGroup(group string) *Method {
	m.group = Group(group)
	a = newApi()
	return &a.method
}

func (t Method) WithMethod(method Method) *Path {
	a.method = method
	return &a.path
}

func (t Path) WithPath(path string) HandlerFunc {
	a.path = Path(path)
	return a.handler
}

func (t HandlerFunc) WithHandlerFunc(handlerFunc HandlerFunc) *module {
	a.handler = handlerFunc
	aa := *a
	mm := *m
	if v, ok := moduleMap[mm.key]; ok {
		v.apis = append(v.apis, &aa)
		mm = *v
	} else {
		mm.apis = append(m.apis, &aa)
	}
	moduleMap[mm.key] = &mm
	return m
}
